<script setup lang="ts" name="DataInputOutputDrawer">
import useMessageBox from '@/hooks/useMessageBox'
import { errorMessage } from '@/utils/message'
import { getAssignmentTypeList } from '../../../../utils/dataInputOutput'
import { getScriptTypeList } from '../../../../utils'
import { getScriptType } from '../../../../utils/scriptType'
import { nextId } from '../../../../utils/id'
import DataInputOutputMapAddEdit from './DataInputOutputMapAddEdit.vue'

const { messageBox } = useMessageBox()

const dataFormRef = ref(null)
const DataInputOutputMapAddEditRef = ref(null)
const emit = defineEmits(['save'])

const visible = ref(false)

const type = ref(null)
const isConnector = ref(false)

const form: any = ref({
  name: '',
  type: '',
  definition: {
    entries: [],
    items: []
  },
  stringOrExpression: '',
  script: {
    scriptFormat: '',
    scriptType: '',
    value: '',
    resource: ''
  }
})

const editIndex = ref(-1)

const assignmentTypeList = ref([])
const scriptTypeList = ref([])

const showDrawer = (v) => {
  type.value = v.type
  isConnector.value = v.isConnector
  if (v.row) {
    form.value.name = v.row.name
    form.value.type = v.row.type
    if (v.row.type === 'list') {
      form.value.definition.items = v.row.definition.items
    } else if (v.row.type === 'map') {
      form.value.definition.entries = v.row.definition.entries
    } else if (v.row.type === 'script') {
      form.value.script.scriptType = getScriptType(v.row.definition)
      form.value.script.scriptFormat = v.row.definition.scriptFormat
      if (form.value.script.scriptType === 'inline') {
        form.value.script.value = v.row.definition.value
      } else {
        form.value.script.resource = v.row.definition.resource
      }
    } else {
      form.value.stringOrExpression = v.row.value
    }
  } else {
    form.value.name = nextId(type.value === 'InputParameter' ? 'Input_' : 'Output_')
    form.value.type = 'stringOrExpression'
  }
  assignmentTypeList.value = getAssignmentTypeList()
  scriptTypeList.value = getScriptTypeList()
  visible.value = true
}
defineExpose({ showDrawer })

// 新增映射数据
const add = () => {
  editIndex.value = -1
  DataInputOutputMapAddEditRef.value.showDialog({ index: -1 })
}

// 编辑映射数据
const edit = (row, idx) => {
  editIndex.value = idx
  DataInputOutputMapAddEditRef.value.showDialog({ index: idx, row: row })
}

// 删除映射数据
const deleteRow = (index) => {
  const msg = '确认<span>删除</span>该映射条目吗？'
  const msgTips = ''
  messageBox('danger', true, msg, msgTips, () => {
    form.value.definition.entries.splice(index, 1)
  })
}

// 映射数据更新
const mapEntryChange = (v) => {
  if (editIndex.value === -1) {
    form.value.definition.entries.push(v)
  } else {
    form.value.definition.entries.splice(editIndex.value, 1, v)
  }
}

// 新增列表数据
const addItem = () => {
  editIndex.value = -1
  form.value.definition.items.push({ value: '' })
}

// 删除列表数据
const deleteItem = (index) => {
  const msg = '确认<span>删除</span>该列表值吗？'
  const msgTips = ''
  messageBox('danger', true, msg, msgTips, () => {
    form.value.definition.items.splice(index, 1)
  })
}

// 关闭抽屉
const cancel = () => {
  dataFormRef.value.resetFields()
  form.value = {
    name: '',
    type: '',
    definition: {
      entries: [],
      items: []
    },
    stringOrExpression: '',
    script: {
      scriptFormat: '',
      scriptType: '',
      value: '',
      resource: ''
    }
  }
  visible.value = false
}

const isListValidate = (data) => {
  const res = []
  data.forEach((item) => {
    if (!res.includes(item.value)) {
      res.push(item.value)
    }
  })
  if (data.length !== res.length) {
    return false
  } else {
    return true
  }
}

// 保存监听器数据
const save = async () => {
  await dataFormRef.value.validate((validate) => {
    if (validate) {
      const result = {
        name: form.value.name,
        type: form.value.type
      }
      if (form.value.type === 'list') {
        if (!isListValidate(form.value.definition.items)) {
          errorMessage('列表数据不能有相同值！')
          return false
        }
        result['definition'] = {}
        result['definition']['items'] = form.value.definition.items
      } else if (form.value.type === 'map') {
        result['definition'] = {}
        result['definition']['entries'] = form.value.definition.entries
      } else if (form.value.type === 'stringOrExpression') {
        result['stringOrExpression'] = form.value.stringOrExpression
      } else if (form.value.type === 'script') {
        result['script'] = form.value.script
      }
      emit('save', result)
      cancel()
    }
  })
}

const getDrawerHeaderTitle = () => {
  let res = ''
  if (isConnector.value) {
    if (type.value === 'InputParameter') {
      res = '连接器输入'
    } else {
      res = '连接器输出'
    }
  } else {
    if (type.value === 'InputParameter') {
      res = '输入'
    } else {
      res = '输出'
    }
  }
  return res
}
</script>

<template>
  <el-drawer class="data-input-output-drawer" v-model="visible" direction="rtl" destroy-on-close size="580px" :before-close="cancel">
    <template #header>
      <h2>{{ getDrawerHeaderTitle() }}</h2>
    </template>
    <template #default>
      <el-form :model="form" label-width="auto" label-position="right" ref="dataFormRef" @submit.prevent>
        <el-form-item :label="type === 'InputParameter' ? '局部变量名' : '流程变量名'" :key="form.type" prop="name" :rules="{ required: true, trigger: ['blur', 'change'], message: '变量名不能为空' }">
          <el-input v-model="form.name" />
        </el-form-item>
        <el-form-item label="赋值类型">
          <el-select v-model="form.type">
            <el-option v-for="item in assignmentTypeList" :key="item.value" :label="item.label" :value="item.value" />
          </el-select>
        </el-form-item>
        <template v-if="form.type === 'script'">
          <el-form-item label="脚本格式" prop="script.scriptFormat" :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本格式' }">
            <el-input v-model="form.script.scriptFormat" />
          </el-form-item>
          <el-form-item label="脚本类型" prop="script.scriptType" :rules="{ required: true, trigger: ['blur', 'change'], message: '请选择脚本类型' }">
            <el-select v-model="form.script.scriptType">
              <el-option v-for="item in scriptTypeList" :key="item.value" :label="item.label" :value="item.value" />
            </el-select>
          </el-form-item>
          <el-form-item v-if="form.script.scriptType && form.script.scriptType === 'inline'" label="脚本内容" prop="script.value" :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本内容' }">
            <el-input type="textarea" v-model="form.script.value" />
          </el-form-item>
          <el-form-item v-if="form.script.scriptType && form.script.scriptType === 'external'" label="资源地址" prop="script.resource" :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写资源地址' }">
            <el-input type="textarea" v-model="form.script.resource" />
          </el-form-item>
        </template>
        <el-form-item v-else-if="form.type === 'stringOrExpression'" label="值" prop="stringOrExpression" :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写变量值' }">
          <el-input type="textarea" v-model="form.stringOrExpression" placeholder="请将表达式填写在 '${}' 中" />
        </el-form-item>
      </el-form>
      <div v-if="form.type === 'list'" class="field-content">
        <el-divider>
          <div class="divider-panel">
            <svg-icon icon="ri:brackets-line"></svg-icon>
            <span>列表数据</span>
          </div>
        </el-divider>
        <div class="list-input">
          <div v-for="item, index in form.definition.items" :key="index" class="item-input">
            <el-input v-model="item.value" />
            <el-button type="danger" icon="Delete" circle @click="deleteItem(index)"></el-button>
          </div>
        </div>
        <el-button class="add" type="primary" icon="Plus" @click="addItem">添加列表数据</el-button>
      </div>
      <div v-if="form.type === 'map'" class="field-content">
        <el-divider>
          <div class="divider-panel">
            <svg-icon icon="ri:mind-map"></svg-icon>
            <span>映射条目</span>
          </div>
        </el-divider>
        <el-table :data="form.definition.entries" border>
          <el-table-column type="index" label="序号" width="60" />
          <el-table-column prop="key" label="键" show-overflow-tooltip />
          <el-table-column prop="value" label="值" show-overflow-tooltip />
          <el-table-column prop="operate" label="操作" width="110" align="center">
            <template #default="scope">
              <el-button type="primary" icon="Edit" circle @click="edit(scope.row, scope.$index)"></el-button>
              <el-button type="danger" icon="Delete" circle @click="deleteRow(scope.$index)"></el-button>
            </template>
          </el-table-column>
        </el-table>
        <el-button class="add" type="primary" icon="Plus" @click="add">添加映射条目</el-button>
      </div>
      <DataInputOutputMapAddEdit ref="DataInputOutputMapAddEditRef" :data="form.definition.entries" @save="mapEntryChange"></DataInputOutputMapAddEdit>
    </template>
    <template #footer>
      <div class="drawer-footer">
        <el-button @click="cancel">取消</el-button>
        <el-button type="primary" @click="save">保存</el-button>
      </div>
    </template>
  </el-drawer>
</template>
<style scoped lang="scss">
.field-content {
  padding-right: 6px;

  .el-button.add {
    width: 100%;
    margin: 12px 0 0;
  }
}

.divider-panel {
  display: flex;
  align-items: center;

  span {
    margin-left: 6px;
  }
}

.list-input {

  .item-input {
    display: flex;
    margin-top: calc(var(--el-space) - 8px);

    .el-input {
      flex: 1;
    }

    .el-button {
      margin-left: 12px;
    }
  }
}
</style>
<style lang="scss">
.data-input-output-drawer {

  .el-drawer__header {
    margin: 0;
    padding: 15px var(--el-space);
    border-bottom: 1px solid var(--el-border-color-extra-light);

    h2 {
      font-weight: bold;
      font-size: 14px;
    }
  }

  .el-drawer__body {
    position: relative;
    padding: calc(var(--el-space) - 8px) calc(var(--el-space) - 8px) calc(var(--el-space) - 8px) calc(var(--el-space) - 2px);
  }

  .el-drawer__footer {
    padding: 12px;
    border-top: 1px solid var(--el-border-color-extra-light);

    .drawer-footer {
      display: flex;

      .el-button {
        flex: 1;
        margin: 6px;
      }
    }
  }
}
</style>
